<?php
/**
 * bs多规格sku商城系统
 * ============================================================================
 * 版权所有 2024-2099 wltx666.com，并保留所有权利。
 * 网站地址: https://wltx666.com
 * ============================================================================
 * Author: 草上飞
 * Email: wltx@alipay168.cn
 * QQ: 2719875001
 * Date: 2024/12/16
 * 描述:
 */

namespace app\result;

use app\model\chat\ChatConversationsSummary;
use app\model\coupon\CouponUser;
use app\model\user\User;
use app\model\user\UserLoginLog;
use app\model\user\UserMsg;
use app\service\CreditService;
use app\service\JWTService;
use Endroid\QrCode\ErrorCorrectionLevel;
use Endroid\QrCode\Label\Label;
use Endroid\QrCode\Logo\Logo;
use Endroid\QrCode\QrCode;
use Endroid\QrCode\RoundBlockSizeMode;
use Endroid\QrCode\Writer\PngWriter;
use Endroid\QrCode\Encoding\Encoding;
use Endroid\QrCode\Color\Color;

class UserResult extends BaseResult
{
    public function __construct()
    {
        parent::__construct();
        $this->model = new User();
    }

    //更新最后活跃时间
    public function update_last_active_time($user_id, $data)
    {
        return $this->model->data_update(['user_id' => $user_id], $data);
    }

    public function login($args)
    {
        if (empty($args['encryptedData']) || empty($args['iv'])) {
            return $this->error_return('参数错误');
        }
        $res = ToolsResult::decrypt($args['encryptedData'], config('tools.encode.key'), $args['iv']);
        if (!$res) {
            return $this->error_return('参数非法');
        }
        $args = json_decode($res, true);
        $account = trim($args['account'] ?? "");
        $password = trim($args['password'] ?? '');
        $captcha_code = trim($args['captcha_code'] ?? "");
        $captcha_key = trim($args['captcha_key'] ?? "");
        if (empty($account)) {
            return $this->error_return('登录账号不能为空');
        }
        if (empty($password)) {
            return $this->error_return('密码不能为空');
        }
        if (empty($captcha_code) || empty($captcha_key)) {
            return $this->error_return('验证码不能为空');
        }

        if (!(new CodeResult())->captcha_check($captcha_key, $captcha_code)) {
            return $this->error_return('验证码错误');
        }


        $user = $this->model->data_get(['account' => $account], 'user_id,password,salt,user_code');
        if (!$user) {
            $user = $this->model->data_get(['email' => $account], 'user_id,password,salt,user_code');
            if (!$user) {
                return $this->error_return('账号未注册');
            }
        }
        $up = [];

        if (md5($password . $user['salt']) != $user['password']) {
            return $this->error_return('密码错误');
        }
        $salt = substr(md5(uniqid('', true)), 0, 10);
        $password = md5($password . $salt);
        $up = array_merge($up, [
            'password' => $password,
            'salt' => $salt,
        ]);
        $res = $this->add_user_log($user['user_id'], 1, $up);
        if (!$res) {
            return $this->error_return('登录失败');
        }
        $token = $this->set_token($user['user_code']);
        return $this->success_return('登录成功', ['token' => $token]);
    }

    public function code_login($args)
    {
        if (empty($args['encryptedData']) || empty($args['iv'])) {
            return $this->error_return('参数错误');
        }
        $res = ToolsResult::decrypt($args['encryptedData'], config('tools.encode.key'), $args['iv']);
        if (!$res) {
            return $this->error_return('参数非法');
        }
        $args = json_decode($res, true);
        $account = trim($args['account'] ?? "");
        $code = trim($args['code'] ?? "");
        $captcha_code = trim($args['captcha_code'] ?? "");
        $captcha_key = trim($args['captcha_key'] ?? "");
        if (empty($account)) {
            return $this->error_return('请输入手机号或者邮箱');
        }
        if (empty($code)) {
            return $this->error_return('请输入验证码');
        }
        if (empty($captcha_code) || empty($captcha_key)) {
            return $this->error_return('验证码不能为空');
        }

        if (!(new CodeResult())->captcha_check($captcha_key, $captcha_code)) {
            return $this->error_return('图形验证码错误', $args);
        }

        $checkCode = (new CodeResult())->check_code($account, $code, 2);
        if ($checkCode['code'] <> 0) {
            return $checkCode;
        }
        $where = [
            ['email', '=', $account],
        ];
        //如果是手机号
        if (preg_match("/^1[3456789]\d{9}$/", $account)) {
            $where = [
                ['mobile', '=', $account],
            ];
        }

        $user = $this->model->data_get($where, 'user_id,password,salt,user_code');
        if (!$user) {
            $user = $this->model->data_get(['account' => $account], 'user_id,password,salt,user_code');
            if (!$user) {
                return $this->error_return('账号未注册');
            }
        }
        $res = $this->add_user_log($user['user_id'], 2);
        if (!$res) {
            return $this->error_return('登录失败');
        }
        $token = $this->set_token($user['user_code']);
        return $this->success_return('登录成功', ['token' => $token]);
    }

    //设置token
    private function set_token($user_code)
    {
        $payload = [
            "iss" => request()->domain(), // 使用当前请求域名作为签发者
            "aud" => request()->domain(), // 使用当前请求域名作为受众
            "iat" => time(), // 当前时间戳作为签发时间
            "nbf" => time(), // 0秒后生效
            "exp" => time() + 86400 * 60, // 有效期
            "sub" => $user_code, // 用户代码作为主题
            "jti" => uniqid('', true), // 唯一的JWT ID
        ];

        $service = new JWTService();
        return $service->encode($payload);
    }

    //更新登录信息
    private function add_user_log($user_id, $type, $update_data = [])
    {
        $update_data = array_merge($update_data, [
            'last_login_ip' => request()->ip(),
            'last_login_time' => date('Y-m-d H:i:s'),
        ]);
        (new UserLoginLog())->data_add([
            'user_id' => $user_id,
            'type' => $type,//1=密码，2=短信
            'login_ip' => request()->ip(),
        ]);
        return (new User())->data_update(['user_id' => $user_id], $update_data);
    }

    private function getNickname(): string
    {
        // 定义更多形容词
        $adjectives = ['梦幻', '星辰', '夜色', '晨曦', '幽静', '灵动', '炽烈', '温柔', '神秘', '璀璨',
            '皎洁', '绚烂', '飘逸', '清冷', '优雅', '深邃', '宁静', '温暖', '逍遥', '浩瀚', '清风',
            '空灵', '婉约', '磅礴', '静谧', '绚彩', '流光', '逸致', '清幽', '高远', '苍茫',
            '绮丽', '悠然', '潋滟', '澄澈', '芳馨', '馥郁', '玄妙', '超凡', '脱俗', '恬淡',
            '素雅', '婀娜', '巍峨', '浩渺', '斑斓', '柔和', '寂寥', '明快', '纯净', '古朴'];
        // 定义更多名词
        $nouns = ['飞鸟', '流云', '微风', '细雨', '繁花', '明月', '清泉', '远山', '暮雪', '流星',
            '苍穹', '碧海', '红叶', '紫霞', '青松', '白雪', '金阳', '银霜', '丹心', '墨竹', '松花',
            '飞鸿', '晨露', '晚霞', '秋水', '寒梅', '春草', '夏荷', '冬柏', '玉兔', '金乌',
            '瑶池', '翠柳', '绿萝', '黄鹂', '紫藤', '青鸾', '白鹭', '红枫', '墨菊', '锦鲤',
            '幽兰', '瑞雪', '祥云', '碧波', '银河', '瀑布', '彩虹', '草原', '沙漠', '森林'];
        // 可选的连接符
        $connectors = ['之', '与', '于', '若', '如', '', '-', '·']; // 包含空字符串以表示不使用连接符
        // 随机选择一个形容词、名词和连接符
        $adjectiveKey = array_rand($adjectives);
        $nounKey = array_rand($nouns);
        $connectorKey = array_rand($connectors);
        // 组合元素，创建网名
        return $adjectives[$adjectiveKey] . $connectors[$connectorKey] . $nouns[$nounKey];
    }

    public function register($args)
    {
        if (empty($args['encryptedData']) || empty($args['iv'])) {
            return $this->error_return('参数错误');
        }
        $res = ToolsResult::decrypt($args['encryptedData'], config('tools.encode.key'), $args['iv']);
        if (!$res) {
            return $this->error_return('参数非法');
        }
        $args = json_decode($res, true);
        $account = trim($args['account'] ?? "");
        $password = trim($args['password'] ?? '');
        $password1 = trim($args['password1'] ?? '');
        $captcha_code = trim($args['captcha_code'] ?? "");
        $captcha_key = trim($args['captcha_key'] ?? "");
        $invite_code = trim($args['invite_code'] ?? "");//邀请码
        if (empty($account)) {
            return $this->error_return('请输入账号', $args);
        }
        if (empty($password)) {
            return $this->error_return('请输入密码');
        }
        if ($password != $password1) {
            return $this->error_return('两次密码不一致');
        }
        if (empty($captcha_code) || empty($captcha_key)) {
            return $this->error_return('验证码不能为空');
        }

        if (!(new CodeResult())->captcha_check($captcha_key, $captcha_code)) {
            return $this->error_return('验证码错误');
        }
        if (strlen($account) < 3) {
            return $this->error_return('账号长度不能小于3位');
        }

        //判断密码不可以小于6位，大于16位
        if (strlen($args['password']) < 6 || strlen($args['password']) > 16) {
            return $this->error_return('密码长度为6-16位');
        }
        //密码只能是数字、字母、下划线
        if (!preg_match('/^[0-9a-zA-Z_]+$/', $args['password'])) {
            return $this->error_return('密码只能是数字、字母、下划线');
        }
        if ($invite_code) {
            $user_info = (new User())->data_get(['user_code' => $invite_code], 'user_id,user_code,status,parent_id');
            if (!$user_info) {
                return $this->error_return('邀请码错误');
            }
            if ($user_info['status'] == -1) {
                return $this->error_return('邀请用户账号异常，无法使用');
            }
            $parent_id = $user_info['user_id'];
            if ($user_info['parent_id']) {
                $source_parent_id = (new User())->get_value(['user_id' => $user_info['parent_id']], 'user_id');
            }

        }

        $args['password'] = trim($args['password']);
        $user_code = $this->get_user_code();
        $salt = substr(md5(uniqid('', true)), 0, 10);
        $password = md5($args['password'] . $salt);
        if (empty($args['username'])) {
            //截取手机号后面4位
            $args['username'] = $this->getNickname();
        }
        $user = $this->model->data_get(['account' => $account], 'user_id');
        if ($user) {
            return $this->error_return('账号已存在');
        }
        //判断是不是email
        if (filter_var($account, FILTER_VALIDATE_EMAIL)) {
            $args['email'] = $account;
            if ($this->model->data_get(['email' => $account])) {
                return $this->error_return('邮箱已存在');
            }
        }

        $baseData = [
            'avatar' => 'https://source.alipay168.cn/skushop/a09abe75bda9081150e17df84e494ffa.png',
            'username' => $args['username'],
            'account' => $account,
            'password' => $password,
            'salt' => $salt,
            'user_code' => $user_code,
            'parent_id' => $parent_id ?? 0,
            'source_parent_id' => $source_parent_id ?? 0,
        ];

        $user_id = (new User())->data_add($baseData);
        if (!$user_id) {
            return $this->error_return('注册失败');
        }
        (new UserMsgResult())->add($user_id, [
            'title' => '注册成功，请记录账号',
            'content' => '系统已为您创建了账号：<b style="color:red">' . $account . '</b>，登录后即可开始使用。如需要修改账号关联数据，请通过【设置》安全中心》账号修改】进行修改为自己想要的账号。',
            'type' => 1,
            'path_info' => [
                'title' => '安全中心',
                'path' => '/pages/setting/safe/index',
                'jump_type' => 'inner',//inner=内页，tab=底部导航，link=外链
            ],
        ]);
        return $this->success_return('注册成功', ['user_code' => $user_code]);
    }

    private function get_user_code()
    {
        //生成8位数,纯数字邀请码
        $todayRegCount = $this->model->data_count([['created_at', '>=', date('Y-m-d 00:00:00')]], 'user_id');
        $utr = $todayRegCount + 1;
        //不足2位，补0
        $utr = str_pad(strval($utr), 2, '0', STR_PAD_LEFT);

        $user_code = '1' . $utr . rand(10000, 99999);
        //去重
        while (true) {
            $user_code_user = $this->model->get_value(['user_code' => $user_code], 'user_id');
            if (!$user_code_user) {
                break;
            }
            $user_code = '1' . $utr . rand(10000, 99999);
        }
        return $user_code;
    }

    public function logout($token, $user_id = 0)
    {
        if ($token) {
            $token_cache = 'user_token_' . md5($token);
            cache($token_cache, 1, 86400 * 7);
        }
        return self::success_return('退出成功');
    }

    public function info($user_id)
    {
        $model = new User();

        $user = $model->data_get(['user_id' => $user_id], 'account,user_id,email,mobile,avatar,username as nick_name,user_code,cancel_expire,created_at,credit,point');
        if (!$user) {
            return $this->error_return('用户不存在');
        }
        $user = $user->toArray();
        if (!empty($user['cancel_expire'])) {
            $user['cancel_expire'] = date('Y-m-d H:i:s', $user['cancel_expire']);
        }

        $user['unread_count'] = (new UserMsg())->data_count(['user_id' => $user['user_id'], 'read_time' => 0]);//未读消息数

        CouponResult::update_expire_coupon($user['user_id']);
        $user['coupon_count'] = (new CouponUser())->data_count(['user_id' => $user['user_id'], 'status' => 0]);

        if (empty($user['avatar'])) {
            $user['avatar'] = 'https://source.alipay168.cn/skushop/a09abe75bda9081150e17df84e494ffa.png';
        }
        $user['kefuMsgCount'] = (new ChatConversationsSummary())->data_sum(['user_id' => $user['user_id'], 'is_deleted' => 0,], 'unread_count') ?: 0;
        return $this->success_return('success', $user);
    }

    public function get_token_user($token, $field = '*')
    {
        // 判断token是否已执行过退出
        if (cache('user_token_' . md5($token))) {
            return self::error_return('token无效');
        }
        try {
            $decode = (new JWTService())->decode($token);
        } catch (\Exception $e) {
            return self::error_return('token已过期', $e->getMessage());
        };

        if (isset($decoded->exp) && $decoded->exp < time()) {
            return self::error_return('token已过期');
        }

        // 检查'nbf'声明以确认当前时间是否在令牌生效之前
        if (isset($decoded->nbf) && $decoded->nbf > time()) {
            return self::error_return('token未生效，请等待一段时间再试');
        }

        $user_code = $decode->sub;
        if (!$user_code) {
            return self::error_return('用户不存在');
        }
        $user = (new User())->data_get(['user_code' => $user_code], $field);
        if (!$user) {
            return self::error_return('用户不存在');
        }
        return self::success_return('success', $user);
    }

    //更新基本信息
    public function update_info($user_id, $data): array
    {
        if (!request()->isPut()) {
            return $this->error_return('非法请求');
        }
        if (!empty($data['nick_name']) && mb_strlen($data['nick_name']) > 10) {
            return $this->error_return('昵称长度不能超过10个字符');
        }
        $up = [];
        if (!empty($data['avatar'])) {
            $up['avatar'] = $data['avatar'];

        }
        if (!empty($data['nick_name'])) {
            $up['username'] = $data['nick_name'];
        }
        (new User())->data_update(['user_id' => $user_id], $up);
        return $this->success_return('更新成功');
    }

    //忘记密码
    public function forget_password($args)
    {
        if (empty($args['encryptedData']) || empty($args['iv'])) {
            return $this->error_return('参数错误');
        }
        $res = ToolsResult::decrypt($args['encryptedData'], config('tools.encode.key'), $args['iv']);
        if (!$res) {
            return $this->error_return('参数非法');
        }
        $args = json_decode($res, true);
        $account = trim($args['email'] ?? "");
        $code = trim($args['code'] ?? "");
        $password = trim($args['password'] ?? "");
        if (empty($account)) {
            return $this->error_return('请输入绑定的邮箱');
        }
        if (empty($code)) {
            return $this->error_return('请输入验证码');
        }
        if (empty($password)) {
            return $this->error_return('请输入新密码');
        }
        //判断密码不可以小于6位，大于16位
        if (strlen($password) < 6 || strlen($password) > 16) {
            return $this->error_return('密码长度仅限6-16位');
        }
        //密码只能是数字、字母、下划线
        if (!preg_match('/^[0-9a-zA-Z_]+$/', $password)) {
            return $this->error_return('密码只能是数字、字母、下划线');
        }
        $checkCode = (new CodeResult())->check_code($account, $code, 3);
        if ($checkCode['code'] <> 0) {
            return $checkCode;
        }

        $myInfo = (new User())->data_get(['email' => $account], 'user_id,account,account_edit_time,salt,password');
        if (!$myInfo) {
            return $this->error_return('账号不存在');
        }

        $salt = substr(md5(uniqid('', true)), 0, 10);
        $password = md5($password . $salt);
        $up = [
            'password' => $password,
            'salt' => $salt,
        ];
        $res = (new User())->data_update(['user_id' => $myInfo['user_id']], $up);
        UserMsgResult::add($myInfo['user_id'], [
            'title' => '登录密码修改通知',
            'content' => '您的登录账号已修改，请使用新密码进行登录，请牢记新密码，请勿泄露给别人。',
            'type' => 1
        ]);
        return $res ? $this->success_return('修改成功') : $this->error_return('修改失败');
    }

    //修改账号
    public function update_account($user_id, $args): array
    {
        if (empty($args['encryptedData']) || empty($args['iv'])) {
            return $this->error_return('参数错误');
        }
        $res = ToolsResult::decrypt($args['encryptedData'], config('tools.encode.key'), $args['iv']);
        if (!$res) {
            return $this->error_return('参数非法');
        }
        $args = json_decode($res, true);
        $account = $args['account'] ?? '';
        $password = $args['password'] ?? '';
        if (empty($account)) {
            return $this->error_return('账号不能为空');
        } elseif (mb_strlen($account) > 40) {
            return $this->error_return('账号不能超过40个字符');
        }
        if (empty($password)) {
            return $this->error_return('密码不能为空');
        }

        $user = (new User())->data_get(['account' => $account], 'user_id');
        if ($user && $user['user_id'] != $user_id) {
            return $this->error_return('账号已存在');
        }
        $myInfo = (new User())->data_get(['user_id' => $user_id], 'account,account_edit_time,salt,password');
        if ($account == $myInfo['account']) {
            return $this->error_return('账号未修改');
        }
        if ($myInfo['account_edit_time'] + 86400 * 30 > time()) {
            return $this->error_return('30天内只能修改一次，还有' . intval(($myInfo['account_edit_time'] + 86400 * 30 - time()) / 86400) . '天可修改');
        }
        if (md5($password . $myInfo['salt']) <> $myInfo['password']) {
            return $this->error_return('密码错误');
        }
        $res = (new User())->data_update(['user_id' => $user_id], ['account' => $account, 'account_edit_time' => time()]);
        UserMsgResult::add($user_id, [
            'title' => '账号修改通知',
            'content' => '账号已修改为：<b style="color:red">' . $account . '</b>，请使用新账号进行登录。',
            'type' => 1
        ]);
        return $res ? $this->success_return('修改成功') : $this->error_return('修改失败');
    }

    //注销账号
    public function account_cancel($user_id, $args): array
    {
        if (empty($args['encryptedData']) || empty($args['iv'])) {
            return $this->error_return('参数错误');
        }
        $res = ToolsResult::decrypt($args['encryptedData'], config('tools.encode.key'), $args['iv']);
        if (!$res) {
            return $this->error_return('参数非法');
        }
        $args = json_decode($res, true);
        $password = $args['password'] ?? '';

        if (empty($password)) {
            return $this->error_return('密码不能为空');
        }
        $myInfo = (new User())->data_get(['user_id' => $user_id], 'account,account_edit_time,salt,password,cancel_expire');
        if (!empty($myInfo['cancel_expire'])) {
            return $this->error_return('账号已申请注销，请于' . date('Y-m-d H:i:s', $myInfo['cancel_expire']) . '后可重新注册');
        }

        if (md5($password . $myInfo['salt']) <> $myInfo['password']) {
            return $this->error_return('密码错误');
        }
        $expire = time() + 86400 * 7;
        $res = (new User())->data_update(['user_id' => $user_id], ['cancel_expire' => $expire]);
        UserMsgResult::add($user_id, [
            'title' => '注销账号通知',
            'content' => '账号：<b style="color:red">' . $myInfo['account'] . '</b>已经申请注销，7天后将彻底注销，如果想取消注销，请于' . date('Y-m-d H:i:s', $expire) . '前登录账号并到注销页面取消注销。',
            'type' => 1
        ]);
        return $res ? $this->success_return('操作成功') : $this->error_return('操作失败');
    }

    //取消注销
    public function regret_cancel($user_id, $args): array
    {
        if (empty($args['encryptedData']) || empty($args['iv'])) {
            return $this->error_return('参数错误');
        }
        $res = ToolsResult::decrypt($args['encryptedData'], config('tools.encode.key'), $args['iv']);
        if (!$res) {
            return $this->error_return('参数非法');
        }
        $args = json_decode($res, true);
        $password = $args['password'] ?? '';

        if (empty($password)) {
            return $this->error_return('密码不能为空');
        }
        $myInfo = (new User())->data_get(['user_id' => $user_id], 'account,account_edit_time,salt,password,cancel_expire');
        if (empty($myInfo['cancel_expire'])) {
            return $this->error_return('账号没有申请注销');
        }
        $res = (new User())->data_update(['user_id' => $user_id], ['cancel_expire' => 0]);
        UserMsgResult::add($user_id, [
            'title' => '注销账号通知',
            'content' => '账号：<b style="color:red">' . $myInfo['account'] . '</b>已经取消注销，可以正常使用。',
            'type' => 1
        ]);
        return $res ? $this->success_return('操作成功') : $this->error_return('操作失败');
    }

    ////不能是连续的6位数和倒序的6位数，和相同的6字符
    private function check_password($password)
    {
        if (empty($password)) {
            return $this->error_return('密码不能为空');
        } elseif (mb_strlen($password) < 6) {
            return $this->error_return('密码长度不能小于6位');
        } elseif (mb_strlen($password) > 20) {
            return $this->error_return('密码长度不能大于20位');
        }
        if (in_array($password, ['123456', '654321', '123321', '321123', '888888', '111111', '000000'])) {
            return $this->error_return('密码太不安全了，请重新设置');
        }
        return self::success_return('密码格式正确');
    }

    //修改账号登录密码
    public function update_password($user_id, $arg): array
    {
        if (empty($arg['encryptedData']) || empty($arg['iv'])) {
            return $this->error_return('参数错误');
        }
        $res = ToolsResult::decrypt($arg['encryptedData'], config('tools.encode.key'), $arg['iv']);
        if (!$res) {
            return $this->error_return('参数非法');
        }
        $arg = json_decode($res, true);
        $password = $arg['password'] ?? '';
        if (empty($password)) {
            return $this->error_return('请输入原密码');
        }
        if (empty($arg['new_password'])) {
            return $this->error_return('请输入新密码');
        }
        $new_password = trim($arg['new_password']);
        if (empty($arg['new_password_confirm'])) {
            return $this->error_return('请再次输入新密码');
        }
        if ($new_password <> $arg['new_password_confirm']) {
            return $this->error_return('两次输入的密码不一致');
        }

        $check_password = $this->check_password($new_password);
        if ($check_password['code'] <> 0) {
            return $check_password;
        }

        $myInfo = (new User())->data_get(['user_id' => $user_id], 'account,account_edit_time,salt,password');

        if (md5($password . $myInfo['salt']) <> $myInfo['password']) {
            return $this->error_return('原密码错误');
        }
        $salt = substr(md5(uniqid('', true)), 0, 10);
        $password = md5($new_password . $salt);
        $up = [
            'password' => $password,
            'salt' => $salt,
        ];

        $res = (new User())->data_update(['user_id' => $user_id], $up);
        UserMsgResult::add($user_id, [
            'title' => '登录密码修改通知',
            'content' => '您的登录账号已修改，请使用新密码进行登录，请牢记新密码，请勿泄露给别人。',
            'type' => 1
        ]);
        return $res ? $this->success_return('修改成功') : $this->error_return('修改失败');
    }

    //更新邮箱
    public function update_email($user_id, $args): array
    {
        $email = $args['email'] ?? '';
        $code = $args['code'] ?? '';
        if (empty($email)) {
            return $this->error_return('邮箱不能为空');
        } elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            return $this->error_return('邮箱格式不正确');
        } elseif (mb_strlen($email) > 60) {
            return $this->error_return('邮箱长度不能超过60个字符');
        } elseif (empty($code)) {
            return $this->error_return('验证码不能为空');
        }
        $user = (new User())->data_get(['email' => $email], 'user_id');
        if ($user && $user['user_id'] != $user_id) {
            return $this->error_return('邮箱已被其他账户使用');
        }
        $code = (new CodeResult())->check_code($email, $code);
        if ($code['code'] <> 0) {
            return $code;
        }
        $res = (new User())->data_update(['user_id' => $user_id], ['email' => $email]);
        UserMsgResult::add($user_id, [
            'title' => '邮箱修改通知',
            'content' => '您的邮箱已修改为：<b style="color:red">' . $email . '</b>，请使用新邮箱接收数据,邮箱也可以用于找回密码、登录等操作。',
            'type' => 1
        ]);
        return $res ? $this->success_return('修改成功') : $this->error_return('邮箱未修改');
    }

    //更新手机号
    public function update_phone($user_id, $args)
    {
        if (empty($args['encryptedData']) || empty($args['iv'])) {
            return $this->error_return('参数错误');
        }
        $res = ToolsResult::decrypt($args['encryptedData'], config('tools.encode.key'), $args['iv']);
        if (!$res) {
            return $this->error_return('参数非法');
        }
        $args = json_decode($res, true);
        $mobile = trim($args['mobile'] ?? "");
        $code = trim($args['code'] ?? "");
        if (empty($mobile)) {
            return $this->error_return('请输入手机号码');
        }
        if (empty($code)) {
            return $this->error_return('请输入验证码');
        }

        $code = (new CodeResult())->check_code($mobile, $code);
        if ($code['code'] <> 0) {
            return $code;
        }
        $user = (new User())->data_get(['mobile' => $mobile], 'user_id');
        if ($user && $user['user_id'] != $user_id) {
            return $this->error_return('手机号已被其他账户使用');
        }
        $user = $this->model->data_get(['account' => $mobile], 'user_id');
        if ($user && $user['user_id'] != $user_id) {
            return $this->error_return('手机号已被其他账户使用');
        }
        $res = (new User())->data_update(['user_id' => $user_id], ['mobile' => $mobile]);
        UserMsgResult::add($user_id, [
            'title' => '手机号修改通知',
            'content' => '您的手机已修改为：<b style="color:red">' . mb_substr($mobile, 0, 3) . '****' . mb_substr($mobile, -4) . '</b>',
            'type' => 1
        ]);
        return $res ? $this->success_return('手机号已经修改') : $this->error_return('手机号未修改');
    }

    /**
     * 获取用户列表
     * @return array
     */
    public function list($args = [])
    {
        $page = request()->param('page', 1, 'intval');
        $pageSize = request()->param('limit', 10, 'intval');
        $sort = request()->param('sort', '', 'trim');
        $cancel_expire = intval($args['cancel_expire'] ?? 0);
        $active_time = $args['active_time'] ?? [];
        $where = [];
        if (!empty($args['keyword'])) {
            $where[] = ['username|account|user_id|email|remark', 'like', '%' . trim($args['keyword']) . '%'];
        }
        if ($cancel_expire) {
            $where[] = ['cancel_expire', '>', 0];
        }
        if ($active_time) {
            $where[] = ['last_active_time', 'between', $active_time];
        }
        $orderBy = 'user_id desc';
        if ($sort == 'created_at') {
            $orderBy = 'created_at asc';
        } elseif ($sort == 'last_login_time') {
            $orderBy = 'last_login_time desc';
        } elseif ($sort == 'updated_at') {
            $orderBy = 'updated_at DESC';
        } elseif ($sort == 'last_active_at') {
            $orderBy = 'last_active_time DESC';
        } elseif ($sort == 'bill_count') {
            $orderBy = 'all_bill_count DESC';
        }
        $total = $this->model->data_count($where);
        $data = $this->model->data_list($where, '*', $orderBy, $page, $pageSize);
        if ($data) {
            foreach ($data as &$v) {
                $v['cash_count'] = $v['all_bill_count'];
                $v['last_active_platform'] = ($v['last_active_platform'] ?: 'unknown');
                if ($v['last_active_version']) {
                    $v['last_active_platform'] = $v['last_active_platform'] . '-' . $v['last_active_version'];
                }
                if ($v['cancel_expire']) {
                    $v['cancel_expire'] = date('Y-m-d H:i:s', $v['cancel_expire']);
                }
            }
            unset($v);
        }
        return $this->success_return('success', [
            'total' => $total,
            'list' => $data
        ]);
    }

    /**
     * 获取指定用户信息
     * @param int $user_code 用户user_code
     * @return array
     */
    public function get(int $user_code): array
    {
        $user = (new User())->data_get(['user_code' => $user_code]);
        return self::success_return('success', $user);
    }

    public function save($args = [])
    {
        $user_id = intval($args['user_id']);
        $password = $args['password'] ?? '';
        $remark = $args['remark'] ?? '';
        if (!$user_id) {
            return $this->error_return('请选择需要修改的用户');
        }
        if (!$password && !$remark) {
            return $this->error_return('请输入修改内容');
        }
        $update_data = [];
        if ($password) {
            $salt = substr(md5(uniqid('', true)), 0, 10);
            $password = md5($args['password'] . $salt);
            $update_data['password'] = $password;
            $update_data['salt'] = $salt;
        }
        if ($remark) {
            $update_data['remark'] = $remark;
        }
        $user = $this->model->data_update(['user_id' => $user_id], $update_data);
        return $this->success_return('success', $user);
    }

    public function options($args = [])
    {
        $keywords = $args['keywords'] ?? '';
        $where = [];
        $limit = 10;
        if ($keywords) {
            $where[] = ['username|account|user_id|email|remark', 'like', '%' . trim($keywords) . '%'];
        }
        $data = $this->model->data_list($where, 'user_id,username,account', 'user_id desc', 1, $limit);
        if ($data) {
            foreach ($data as &$v) {
                $v['label'] = $v['username'] . '(' . $v['account'] . ')';
                $v['value'] = $v['user_id'];
            }
            unset($v);
        }
        return $this->success_return('success', [
            'list' => $data,
        ]);
    }

    public function center($user_id)
    {
        $user = (new User())->data_get(['user_id' => $user_id]);
        $qrcode = $this->share_code($user);
        if (!$qrcode) {
            return $qrcode;
        }
        $data = [
            'avatar' => $user['avatar'] ?? '',
            'level' => $user['level'] ?? '普通会员',
            'balance' => $user['credit'] ?? 0,
            'points' => $user['point'] ?? 0,
            'user_code' => $user['user_code'] ?? '',
            'levelProgress' => $user['level_progress'] ?? 30,
            'share_code' => $qrcode['data']['url'] ?? '',
            'username' => $user['username'] ?? '未设置',
        ];
        return $this->success_return('success', [
            'info' => $data,
            'qrcode' => $qrcode,
        ]);
    }

    private function share_code($user): array
    {
        try {
            $writer = new PngWriter();

            // Create QR code
            $qrCode = new QrCode(
                data: $user['user_code'],
                encoding: new Encoding('UTF-8'),
                errorCorrectionLevel: ErrorCorrectionLevel::Low,
                size: 200,
                margin: 5,
                roundBlockSizeMode: RoundBlockSizeMode::Margin,
                foregroundColor: new Color(0, 0, 0),
                backgroundColor: new Color(255, 255, 255)
            );

            // Create generic logo
            $logo = new Logo(
            //path: __DIR__ . '/assets/bender.png',
                path: $user['avatar'],
                resizeToWidth: 35,
                resizeToHeight: 35,
                punchoutBackground: true
            );

            // Create generic label
            $label = new Label(
                text: $user['username'] ?? "",
                textColor: new Color(255, 0, 0)
            );

            $result = $writer->write($qrCode, $logo, $label);

            // Save it to a file
            $path = app()->getRootPath() . 'public/storage/qrcode/';
            if (!is_dir($path)) {
                @mkdir($path, 0777, true);
            }
            if (!is_dir($path) || !is_writable($path)) {
                return $this->error_return($path . '目录不存在或没有写入权限');
            }
            $path .= 'share_' . $user['user_code'] . '.png';
            $result->saveToFile($path);
            if (!file_exists($path)) {
                return $this->error_return('生成二维码失败');
            }
        } catch (\Exception $e) {
            return $this->error_return($e->getMessage());
        }

        return self::success_return('success', [
            'url' => request()->domain() . '/storage/qrcode/share_' . $user['user_code'] . '.png'
        ]);
    }

    public function recharge($args): array
    {
        $user_id = intval($args['user_id']);
        $money = floatval($args['money']);
        $remark = $args['remark'] ?? '';
        if (!$user_id) {
            return $this->error_return('请选择需要充值的用户');
        }
        if ($money <= 0) {
            return $this->error_return('请输入充值金额');
        }
        if (!$remark) {
            return $this->error_return('请输入充值备注');
        }
        $res = CreditService::credit_action($user_id, $money, [
            'remark' => $remark,
        ]);
        if (!$res) {
            return $this->error_return('充值失败');
        }
        admin_log('用户' . $user_id . '充值' . $money . '元', $args);

        return $this->success_return('充值成功');
    }
}
